/*
 * Copyright (c) 2022, listenai
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT galaxyc_gc032a

#include <zephyr/kernel.h>
#include <zephyr/device.h>

#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/video.h>
#include <drivers/csk6_video_extend.h>

#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(gc032a);

/** 
  * @brief  GC032A ID  
  */  
#define  GC032A_ID    0x23

struct gc032a_data {
    const struct i2c_dt_spec i2c_bus;
    const struct gpio_dt_spec reset_gpios;
	const struct gpio_dt_spec pwdn_gpios;
	struct video_format fmt;
};

struct gc032a_reg {
	uint8_t addr;
	uint8_t value;
};

/*bgr565 */
static const struct gc032a_reg gc032a_init_grb_reg_tb[] = {
	{0xf3, 0xff}, {0xf7, 0x01}, {0xf8, 0x03}, {0xf9, 0xce}, {0xfa, 0x00}, {0xfc, 0x02},
	{0xfe, 0x02}, {0x81, 0x03}, {0xfe, 0x00}, {0x77, 0x64}, {0x78, 0x40}, {0x79, 0x60},

	{0xfe, 0x00}, {0x03, 0x01}, {0x04, 0xcb}, {0x05, 0x01}, {0x06, 0xb2}, {0x07, 0x00},
	{0x08, 0x10},

	{0x0a, 0x00}, {0x0c, 0x00}, {0x0d, 0x01}, {0x0e, 0xe8}, {0x0f, 0x02}, {0x10, 0x88},

	{0x17, 0x54}, {0x19, 0x08}, {0x1a, 0x0a}, {0x1f, 0x40}, {0x20, 0x30}, {0x2e, 0x80},
	{0x2f, 0x2b}, {0x30, 0x1a}, {0xfe, 0x02}, {0x03, 0x02}, {0x05, 0xd7}, {0x06, 0x60},
	{0x08, 0x80}, {0x12, 0x89},

	{0xfe, 0x00}, {0x18, 0x02}, {0xfe, 0x02}, {0x40, 0x22}, {0x45, 0x00}, {0x46, 0x00},
	{0x49, 0x20}, {0x4b, 0x3c}, {0x50, 0x20}, {0x42, 0x10},

	{0xfe, 0x01}, {0x0a, 0xc5}, {0x45, 0x00}, {0xfe, 0x00}, {0x40, 0xff}, {0x41, 0x25},
	{0x42, 0xef}, {0x43, 0x10}, {0x44, 0x82}, {0x46, 0x22}, {0x49, 0x03}, {0x52, 0x02},
	{0x54, 0x00}, {0xfe, 0x02}, {0x22, 0xf6},

	{0xfe, 0x01}, {0xc1, 0x38}, {0xc2, 0x4c}, {0xc3, 0x00}, {0xc4, 0x2c}, {0xc5, 0x24},
	{0xc6, 0x18}, {0xc7, 0x28}, {0xc8, 0x11}, {0xc9, 0x15}, {0xca, 0x20}, {0xdc, 0x7a},
	{0xdd, 0xa0}, {0xde, 0x80}, {0xdf, 0x88},

	{0xfe, 0x01}, {0x50, 0xc1}, {0x56, 0x34}, {0x58, 0x04}, {0x65, 0x06}, {0x66, 0x0f},
	{0x67, 0x04}, {0x69, 0x20}, {0x6a, 0x40}, {0x6b, 0x81}, {0x6d, 0x12}, {0x6e, 0xc0},
	{0x7b, 0x2a}, {0x7c, 0x0c}, {0xfe, 0x01}, {0x90, 0xe3}, {0x91, 0xc2}, {0x92, 0xff},
	{0x93, 0xe3}, {0x95, 0x1c}, {0x96, 0xff}, {0x97, 0x44}, {0x98, 0x1c}, {0x9a, 0x44},
	{0x9b, 0x1c}, {0x9c, 0x64}, {0x9d, 0x44}, {0x9f, 0x71}, {0xa0, 0x64}, {0xa1, 0x00},
	{0xa2, 0x00}, {0x86, 0x00}, {0x87, 0x00}, {0x88, 0x00}, {0x89, 0x00}, {0xa4, 0xc2},
	{0xa5, 0x9b}, {0xa6, 0xc8}, {0xa7, 0x92}, {0xa9, 0xc9}, {0xaa, 0x96}, {0xab, 0xa9},
	{0xac, 0x99}, {0xae, 0xce}, {0xaf, 0xa9}, {0xb0, 0xcf}, {0xb1, 0x9d}, {0xb3, 0xcf},
	{0xb4, 0xac}, {0xb5, 0x00}, {0xb6, 0x00}, {0x8b, 0x00}, {0x8c, 0x00}, {0x8d, 0x00},
	{0x8e, 0x00}, {0x94, 0x55}, {0x99, 0xa6}, {0x9e, 0xaa}, {0xa3, 0x0a}, {0x8a, 0x00},
	{0xa8, 0x55}, {0xad, 0x55}, {0xb2, 0x55}, {0xb7, 0x05}, {0x8f, 0x00}, {0xb8, 0xc7},
	{0xb9, 0xa0},

	{0xfe, 0x01}, {0xd0, 0x40}, {0xd1, 0x00}, {0xd2, 0x00}, {0xd3, 0xfa}, {0xd4, 0x4a},
	{0xd5, 0x02},

	{0xd6, 0x44}, {0xd7, 0xfa}, {0xd8, 0x04}, {0xd9, 0x08}, {0xda, 0x5c}, {0xdb, 0x02},
	{0xfe, 0x00},

	{0xfe, 0x00}, {0xba, 0x00}, {0xbb, 0x06}, {0xbc, 0x0b}, {0xbd, 0x10}, {0xbe, 0x19},
	{0xbf, 0x26}, {0xc0, 0x33}, {0xc1, 0x3f}, {0xc2, 0x54}, {0xc3, 0x68}, {0xc4, 0x7c},
	{0xc5, 0x8c}, {0xc6, 0x9c}, {0xc7, 0xb4}, {0xc8, 0xc9}, {0xc9, 0xd8}, {0xca, 0xe4},
	{0xcb, 0xee}, {0xcc, 0xf4}, {0xcd, 0xf9}, {0xce, 0xfa}, {0xcf, 0xff},

	{0xfe, 0x00}, {0x5a, 0x08}, {0x5b, 0x0f}, {0x5c, 0x15}, {0x5d, 0x1c}, {0x5e, 0x28},
	{0x5f, 0x36}, {0x60, 0x45}, {0x61, 0x51}, {0x62, 0x6a}, {0x63, 0x7d}, {0x64, 0x8d},
	{0x65, 0x98}, {0x66, 0xa2}, {0x67, 0xb5}, {0x68, 0xc3}, {0x69, 0xcd}, {0x6a, 0xd4},
	{0x6b, 0xdc}, {0x6c, 0xe3}, {0x6d, 0xf0}, {0x6e, 0xf9}, {0x6f, 0xff},

	{0xfe, 0x00}, {0x70, 0x50},

	{0xfe, 0x00}, {0x4f, 0x01}, {0xfe, 0x01}, {0x0c, 0x01}, {0x0d, 0x00}, {0x12, 0xa0},
	{0x13, 0x4a}, {0x44, 0x04}, {0x1f, 0x40}, {0x20, 0x40}, {0x23, 0x0a}, {0x26, 0x9a},
	{0x3e, 0x20}, {0x3f, 0x2d}, {0x40, 0x40}, {0x41, 0x5b}, {0x42, 0x82}, {0x43, 0xb7},
	{0x04, 0x0a}, {0x02, 0x79}, {0x03, 0xc0},

	{0xfe, 0x01}, {0xcc, 0x08}, {0xcd, 0x08}, {0xce, 0xa4}, {0xcf, 0xec},

	{0xfe, 0x00}, {0x81, 0xb8}, {0x82, 0x04}, {0x83, 0x10}, {0x84, 0x01}, {0x86, 0x50},
	{0x87, 0x18}, {0x88, 0x10}, {0x89, 0x70}, {0x8a, 0x20}, {0x8b, 0x10}, {0x8c, 0x08},
	{0x8d, 0x0a},

	{0xfe, 0x00}, {0x8f, 0xaa}, {0x90, 0x1c}, {0x91, 0x52}, {0x92, 0x03}, {0x93, 0x03},
	{0x94, 0x08}, {0x95, 0x6a}, {0x97, 0x00}, {0x98, 0x00},

	{0xfe, 0x00}, {0x9a, 0x30}, {0x9b, 0x50}, {0xa1, 0x30}, {0xa2, 0x66}, {0xa4, 0x28},
	{0xa5, 0x30}, {0xaa, 0x28}, {0xac, 0x32},

	{0xfe, 0x00}, {0xd1, 0x3f}, {0xd2, 0x3f}, {0xd3, 0x38}, {0xd6, 0xf4}, {0xd7, 0x1d},
	{0xdd, 0x72}, {0xde, 0x84},

	{0xfe, 0x00}, {0x05, 0x01}, {0x06, 0xad}, {0x07, 0x00}, {0x08, 0x10},

	{0xfe, 0x01}, {0x25, 0x00}, {0x26, 0x4d},

	{0x27, 0x01}, {0x28, 0xce}, {0x29, 0x01}, {0x2a, 0xce}, {0x2b, 0x01}, {0x2c, 0xce},
	{0x2d, 0x01}, {0x2e, 0xce}, {0x2f, 0x01}, {0x30, 0xce}, {0x31, 0x01}, {0x32, 0xce},
	{0x33, 0x01}, {0x34, 0xce}, {0x3c, 0x10}, {0xfe, 0x00}, {0xfe, 0x00}, {0x44, 0x06},
	{0x46, 0x0f} //
};
/* 25M CLK & VGA & YUV(UYVY) & 15fps */
static const struct gc032a_reg gc032a_init_reg_tb[] = {
    /*System*/
	{0xf3,0xff},
	{0xf5,0x06},
	{0xf7,0x01},
	{0xf8,0x03},
	{0xf9,0xce},
	{0xfa,0x00},
	{0xfc,0x02},
	{0xfe,0x02},
	{0x81,0x03},

	{0xfe,0x00},
	{0x77,0x64},
	{0x78,0x40},
	{0x79,0x60},

	/*Analog&Cisctl*/
	{0xfe,0x00},
	{0x03,0x01},
	{0x04,0xce},
	{0x05,0x01},
	{0x06,0xad},
	{0x07,0x00},
	{0x08,0x10},
	{0x0a,0x00},
	{0x0c,0x00},
	{0x0d,0x01},
	{0x0e,0xe8},
	{0x0f,0x02},
	{0x10,0x88},
	{0x17,0x54},
	{0x19,0x08},
	{0x1a,0x0a},
	{0x1f,0x40},
	{0x20,0x30},
	{0x2e,0x80},
	{0x2f,0x2b},
	{0x30,0x1a},
	{0xfe,0x02},
	{0x03,0x02},
	{0x05,0xd7},
	{0x06,0x60},
	{0x08,0x80},
	{0x12,0x89},

	/*blk*/
	{0xfe,0x00},
	{0x18,0x02},
	{0xfe,0x02},
	{0x40,0x22},
	{0x45,0x00},
	{0x46,0x00},
	{0x49,0x20},
	{0x4b,0x3c},
	{0x50,0x20},
	{0x42,0x10},

	/*isp*/
	{0xfe,0x01},
	{0x0a,0xc5},
	{0x45,0x00},
	{0xfe,0x00},
	{0x40,0xff},
	{0x41,0x25},
	{0x42,0xcf},
	{0x43,0x10},
	{0x44,0x80},//yuv 80 81 82  83
	{0x46,0x22},
	{0x49,0x03},
	{0x52,0x02},
	{0x54,0x00},	
	{0xfe,0x02},
	{0x22,0xf6},

	/*Shading*/
	{0xfe,0x01},
	{0xc1,0x38},
	{0xc2,0x4c},
	{0xc3,0x00},
	{0xc4,0x32},
	{0xc5,0x24},
	{0xc6,0x16},
	{0xc7,0x08},
	{0xc8,0x08},
	{0xc9,0x00},
	{0xca,0x20},
	{0xdc,0x8a},
	{0xdd,0xa0},
	{0xde,0xa6},
	{0xdf,0x75},

	/*AWB*/ /*20170110*/
	{0xfe,0x01},
	{0x7c,0x09},
	{0x65,0x06},
	{0x7c,0x08},
	{0x56,0xf4},
	{0x66,0x0f},
	{0x67,0x84},
	{0x6b,0x80},
	{0x6d,0x12},
	{0x6e,0xb0},
	{0xfe,0x01},
	{0x90,0x00},
	{0x91,0x00},
	{0x92,0xf4},
	{0x93,0xd5},
	{0x95,0x0f},
	{0x96,0xf4},
	{0x97,0x2d},
	{0x98,0x0f},
	{0x9a,0x2d},
	{0x9b,0x0f},
	{0x9c,0x59},
	{0x9d,0x2d},
	{0x9f,0x67},
	{0xa0,0x59},
	{0xa1,0x00},
	{0xa2,0x00},
	{0x86,0x00},
	{0x87,0x00},
	{0x88,0x00},
	{0x89,0x00},
	{0xa4,0x00},
	{0xa5,0x00},
	{0xa6,0xd4},
	{0xa7,0x9f},
	{0xa9,0xd4},
	{0xaa,0x9f},
	{0xab,0xac},
	{0xac,0x9f},
	{0xae,0xd4},
	{0xaf,0xac},
	{0xb0,0xd4},
	{0xb1,0xa3},
	{0xb3,0xd4},
	{0xb4,0xac},
	{0xb5,0x00},
	{0xb6,0x00},
	{0x8b,0x00},
	{0x8c,0x00},
	{0x8d,0x00},
	{0x8e,0x00},
	{0x94,0x50},
	{0x99,0xa6},
	{0x9e,0xaa},
	{0xa3,0x0a},
	{0x8a,0x00},
	{0xa8,0x50},
	{0xad,0x55},
	{0xb2,0x55},
	{0xb7,0x05},
	{0x8f,0x00},
	{0xb8,0xb3},
	{0xb9,0xb6},

	/*CC*/
	{0xfe,0x01},
	{0xd0,0x40},
	{0xd1,0xf8},
	{0xd2,0x00},
	{0xd3,0xfa},
	{0xd4,0x45},
	{0xd5,0x02},

	{0xd6,0x30},
	{0xd7,0xfa},
	{0xd8,0x08},
	{0xd9,0x08},
	{0xda,0x58},
	{0xdb,0x02},
	{0xfe,0x00},

	/*Gamma*/
	{0xfe,0x00},
	{0xba,0x00},
	{0xbb,0x04},
	{0xbc,0x0a},
	{0xbd,0x0e},
	{0xbe,0x22},
	{0xbf,0x30},
	{0xc0,0x3d},
	{0xc1,0x4a},
	{0xc2,0x5d},
	{0xc3,0x6b},
	{0xc4,0x7a},
	{0xc5,0x85},
	{0xc6,0x90},
	{0xc7,0xa5},
	{0xc8,0xb5},
	{0xc9,0xc2},
	{0xca,0xcc},
	{0xcb,0xd5},
	{0xcc,0xde},
	{0xcd,0xea},
	{0xce,0xf5},
	{0xcf,0xff},

	/*Auto Gamma*/                      
	{0xfe,0x00},
	{0x5a,0x08},
	{0x5b,0x0f},
	{0x5c,0x15},
	{0x5d,0x1c},
	{0x5e,0x28},
	{0x5f,0x36},
	{0x60,0x45},
	{0x61,0x51},
	{0x62,0x6a},
	{0x63,0x7d},
	{0x64,0x8d},
	{0x65,0x98},
	{0x66,0xa2},
	{0x67,0xb5},
	{0x68,0xc3},
	{0x69,0xcd},
	{0x6a,0xd4},
	{0x6b,0xdc},
	{0x6c,0xe3},
	{0x6d,0xf0},
	{0x6e,0xf9},
	{0x6f,0xff},

	/*Gain*/
	{0xfe,0x00},
	{0x70,0x50},

	/*AEC*/
	{0xfe,0x00},
	{0x4f,0x01},
	{0xfe,0x01},
	{0x0d,0x00},//08 add 20170110 	
	{0x12,0xa0},
	{0x13,0x3a},
	{0x44,0x04},
	{0x1f,0x30},
	{0x20,0x40},
	{0x26,0x9a},
	{0x3e,0x20},
	{0x3f,0x2d},
	{0x40,0x40},
	{0x41,0x5b},
	{0x42,0x82},
	{0x43,0xb7},
	{0x04,0x0a},
	{0x02,0x79},
	{0x03,0xc0},

	/*measure window*/
	{0xfe,0x01},
	{0xcc,0x08},
	{0xcd,0x08},
	{0xce,0xa4},
	{0xcf,0xec},

	/*DNDD*/
	{0xfe,0x00},
	{0x81,0xb8},
	{0x82,0x12},
	{0x83,0x0a},
	{0x84,0x01},
	{0x86,0x50},
	{0x87,0x18},
	{0x88,0x10},
	{0x89,0x70},
	{0x8a,0x20},
	{0x8b,0x10},
	{0x8c,0x08},
	{0x8d,0x0a},

	/*Intpee*/
	{0xfe,0x00},
	{0x8f,0xaa},
	{0x90,0x9c},
	{0x91,0x52},
	{0x92,0x03},
	{0x93,0x03},
	{0x94,0x08},
	{0x95,0x44},
	{0x97,0x00},
	{0x98,0x00},

	/*ASDE*/
	{0xfe,0x00},
	{0xa1,0x30},
	{0xa2,0x41},
	{0xa4,0x30},
	{0xa5,0x20},
	{0xaa,0x30},
	{0xac,0x32},

	/*YCP*/
	{0xfe,0x00},
	{0xd1,0x3c},
	{0xd2,0x3c},
	{0xd3,0x38},
	{0xd6,0xf4},
	{0xd7,0x1d},
	{0xdd,0x73},
	{0xde,0x84},

	/*Banding*/
	{0xfe,0x00},
	{0x05,0x01},
	{0x06,0xad},
	{0x07,0x00},
	{0x08,0x10},

	{0xfe,0x01},
	{0x25,0x00},
	{0x26,0x9a},

	{0x27,0x04},
	{0x28,0x00}, 
	{0x29,0x04},
	{0x2a,0x00},
	{0x2b,0x04},
	{0x2c,0x00},
	{0x2d,0x04},
	{0x2e,0x00},
	{0x2f,0x04},
	{0x30,0x00},
	{0x31,0x03},
	{0x32,0x02},
	{0x33,0x12},
	{0x34,0x0c},
	{0x3c,0x30},
	{0xfe,0x00},
};


static int gc032a_write_reg(const struct device *dev, uint8_t reg_addr,
			    uint8_t value)
{
	struct gc032a_data *drv_data = dev->data;
	struct i2c_msg msgs;
	uint8_t tx_buf[2];

	tx_buf[0] = reg_addr;
	tx_buf[1] = value;

	msgs.buf = tx_buf;
	msgs.len = 2;
	msgs.flags = I2C_MSG_WRITE | I2C_MSG_STOP;

	return i2c_transfer(drv_data->i2c_bus.bus, &msgs, 1, drv_data->i2c_bus.addr);
}


static int gc032a_read_reg(const struct device *dev, uint8_t reg_addr,
			   uint8_t *value)
{
	struct gc032a_data *drv_data = dev->data;
	struct i2c_msg msgs[2];

	msgs[0].buf = (uint8_t *)&reg_addr;
	msgs[0].len = 1;
	/*
	 * When using I2C to read the registers of the SCCB device,
	 * a stop bit is required after writing the register address
	 */
	msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;

	msgs[1].buf = (uint8_t *)value;
	msgs[1].len = 1;
	msgs[1].flags = I2C_MSG_READ | I2C_MSG_STOP | I2C_MSG_RESTART;

	return i2c_transfer(drv_data->i2c_bus.bus, msgs, 2, drv_data->i2c_bus.addr);
}



int gc032a_modify_reg(const struct device *dev,
		      uint8_t reg_addr,
		      uint8_t clear_mask,
		      uint8_t value)
{
	int ret;
	uint8_t set_value;

	ret = gc032a_read_reg(dev, reg_addr, &set_value);

	if (ret == 0) {
		set_value = (set_value & (~clear_mask)) |
				(set_value & clear_mask);
		ret = gc032a_write_reg(dev, reg_addr, set_value);
	}


	return ret;
}

static int gc032a_write_all(const struct device *dev,
			    const struct gc032a_reg *regs,
			    uint16_t reg_num)
{
	uint16_t i = 0;
	int err;

	for (i = 0; i < reg_num; i++) {
		err = gc032a_write_reg(dev, regs[i].addr, regs[i].value);
		k_sleep(K_MSEC(1));
		if (err) {
			return err;
		}
	}

	return 0;
}

static int gc032a_set_fmt(const struct device *dev,
			  enum video_endpoint_id ep,
			  struct video_format *fmt)
{
	int ret = 0;

	if (fmt->pixelformat == VIDEO_PIX_FMT_VYUY && fmt->height == 480 && fmt->width == 640) {
		ret = gc032a_write_all(dev, gc032a_init_reg_tb, ARRAY_SIZE(gc032a_init_reg_tb));
		if (ret) {
			LOG_ERR("Unable to write gc032a config");
			return ret;
		}

		return 0;
	}
	if (fmt->pixelformat == VIDEO_PIX_FMT_RGB565 && fmt->height == 480 && fmt->width == 640) {
		ret = gc032a_write_all(dev, gc032a_init_grb_reg_tb,
				       ARRAY_SIZE(gc032a_init_grb_reg_tb));
		if (ret) {
			LOG_ERR("Unable to write gc032a config rgb565");
			return ret;
		}

		return 0;
	}
	LOG_ERR("video format unsupported \n");
    return -ENOTSUP;
}

static int gc032a_get_fmt(const struct device *dev,
			  enum video_endpoint_id ep,
			  struct video_format *fmt)
{
	return 0;
}

static int gc032a_stream_start(const struct device *dev)
{
	return 0;
}

static int gc032a_stream_stop(const struct device *dev)
{
	return 0;
}

static const struct video_format_cap fmts[] = {
	{
		.pixelformat = VIDEO_PIX_FMT_VYUY,
		.width_min = 640,
		.width_max = 640,
		.height_min = 480,
		.height_max = 480,
		.width_step = 0,
		.height_step = 0,
	},
	{
	    .pixelformat = VIDEO_PIX_FMT_RGB565,
	    .width_min = 640,
	    .width_max = 640,
	    .height_min = 480,
	    .height_max = 480,
	    .width_step = 0,
	    .height_step = 0,
	},
	{0}
};

static int gc032a_get_caps(const struct device *dev,
			   enum video_endpoint_id ep,
			   struct video_caps *caps)
{
	caps->format_caps = fmts;
	return 0;
}


static int gc032a_init(const struct device *dev)
{
	struct gc032a_data *drv_data = dev->data;
	int ret = 0;
	uint8_t pid;

	if (i2c_configure(drv_data->i2c_bus.bus,
			I2C_SPEED_SET(I2C_SPEED_STANDARD) | I2C_MODE_CONTROLLER)) {
		LOG_ERR("I2C config failed!");
		return -EIO;
	}

	//check chip id
    ret = gc032a_read_reg(dev,0xf0,&pid);
	if (ret) {
		LOG_ERR("Unable to read gc032a pid");
		return -ENODEV;
	}

	if(pid != GC032A_ID){
		LOG_ERR("gc032a read PID err 0x%x", pid);
		return -ENODEV;		
	 }

	/* Configure Sensor */


	return 0;
}

static int gc032a_set_ctrl(const struct device *dev,
				unsigned int cid, void *value)
{
	int ret = 0;

	switch (cid) {	
	/*
		该sensor只有在mclk有输入时钟的情况下，i2c才能正常通信，所以并不能在内核设备初始化流程中进行sensor初始化。
		目前是通过set_ctrl来提供sensor初始化的api.
	*/
	case 0:
		ret = gc032a_init(dev);
		break;
	default:
		return -ENOTSUP;
	}

	return ret;
}

static const struct video_driver_api gc032a_driver_api = {
	.set_format = gc032a_set_fmt,
	.get_format = gc032a_get_fmt,
	.get_caps = gc032a_get_caps,
	.stream_start = gc032a_stream_start,
	.stream_stop = gc032a_stream_stop,
	.set_ctrl = gc032a_set_ctrl,
};

static int gc032a_init_0(const struct device *dev)
{
	struct gc032a_data *drv_data = dev->data;
	int ret = 0;

	if(drv_data->pwdn_gpios.port){
		gpio_pin_configure_dt(&drv_data->pwdn_gpios, GPIO_OUTPUT_ACTIVE);
		gpio_pin_set_dt(&drv_data->pwdn_gpios, 0);
	}

	if (drv_data->reset_gpios.port) {
        gpio_pin_configure_dt(&drv_data->reset_gpios, GPIO_OUTPUT_ACTIVE);
        gpio_pin_set_dt(&drv_data->reset_gpios, 0);
		k_sleep(K_MSEC(3));
        gpio_pin_set_dt(&drv_data->reset_gpios, 1);
		k_sleep(K_MSEC(1));
	}

	return ret;
}

static struct gc032a_data gc032a_data_0 =
{
    .i2c_bus = I2C_DT_SPEC_GET(DT_DRV_INST(0)),

#if DT_NODE_HAS_PROP(DT_DRV_INST(0), reset_gpios)
    .reset_gpios = GPIO_DT_SPEC_GET(DT_DRV_INST(0), reset_gpios),
#endif

#if DT_NODE_HAS_PROP(DT_DRV_INST(0), pwdn_gpios)
	.pwdn_gpios = GPIO_DT_SPEC_GET(DT_DRV_INST(0), pwdn_gpios),
#endif
};

DEVICE_DT_INST_DEFINE(0, &gc032a_init_0, NULL,
		    &gc032a_data_0, NULL,
		    POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
		    &gc032a_driver_api);
